import { HostRoot } from "./ReactWorkTags";

const concurrentQueues = [];
let concurrentQueuesIndex = 0;

export function finishQueueingConcurrentUpdates() {
    const endIndex = concurrentQueuesIndex;
    concurrentQueuesIndex = 0;
    let i = 0;
    while (i < endIndex) {
        const fiber = concurrentQueues[i++];
        const queue = concurrentQueues[i++];
        const update = concurrentQueues[i++];
        const lane = concurrentQueues[i++];
        if (queue !== null && update !== null) {
            const pending = queue.pending;
            if (pending === null) {
                // 仅有一个update，最新的update指向自己
                update.next = update;
            } else {
                // 最新的update指向第一个update
                update.next = pending.next;
                // 上一次最新的update指向最新的update
                pending.next = update;
            }
            queue.pending = update;
        }
    }
}

export function markUpdateLaneFromFiberToRoot(sourceFiber) {
    // 当前fiber
    let node = sourceFiber;
    // 当前fiber的父fiber
    let parent = sourceFiber.return;
    // 一直向上找，找到根fiber为止
    while (parent !== null) {
        node = parent;
        parent = node.return;
    }
    if (node.tag === HostRoot) {
        return node.stateNode;
    }
    return null;
}

/**
 * 把更新队列添加到更新队列中
 * @date 2023-03-24
 * @param {any} fiber 函数组件对应的fiber
 * @param {any} queue 要更新的hook对应的更新队列
 * @param {any} update 更新对象
 * @returns {any}
 */
export function enqueueConcurrentHookUpdate(fiber, queue, update, lane) {
    enqueueUpdate(fiber, queue, update, lane);
    return getRootForUpdatedFiber(fiber);
};

function getRootForUpdatedFiber(sourceFiber) {
    let node = sourceFiber;
    let parent = node.return;
    while (parent !== null) {
        node = parent;
        parent = node.return;
    }
    return node.tag === HostRoot ? node.stateNode : null;
}

/**
 * 把更新先缓存到concurrentQueues数组中，3个3个一组
 * @date 2023-03-24
 * @param {any} fiber
 * @param {any} queue
 * @param {any} update
 * @returns {any}
 */
function enqueueUpdate(fiber, queue, update, lane) {
    concurrentQueues[concurrentQueuesIndex++] = fiber;
    concurrentQueues[concurrentQueuesIndex++] = queue;
    concurrentQueues[concurrentQueuesIndex++] = update;
    concurrentQueues[concurrentQueuesIndex++] = lane;
};

/**
 * 把更新入队
 * @date 2023-04-08
 * @param {any} fiber 入队的fiber 根fiber
 * @param {any} queue sharedQueue 待生效的队列
 * @param {any} update 更新
 * @param {any} lane 此更新的车道
 * @returns {any}
 */
export function enqueueConcurrentClassUpdate(fiber, queue, update, lane) {
    enqueueUpdate(fiber, queue, update, lane);
    return getRootForUpdatedFiber(fiber);
}
